package com.chejianer.push.service.impl;

import com.chejianer.core.utils.PushCode;
import com.chejianer.push.entity.ClientInfo;
import com.chejianer.push.service.KeyValueService;
import com.chejianer.push.service.PushMessageBySocketIoService;
import com.chejianer.push.utils.SocketThreadUtil;
import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIONamespace;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.listener.ConnectListener;
import com.corundumstudio.socketio.listener.DataListener;
import com.corundumstudio.socketio.listener.DisconnectListener;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.UUID;

/**
 * Created by Chejianer on 2016/10/27.
 */
@Slf4j
@Service
public class PushMessageBySocketIoServiceImpl implements PushMessageBySocketIoService {

    private SocketIONamespace buyerNameSpace;

    private SocketIONamespace vendorNameSpace;

    @Autowired
    private KeyValueService keyValueService;

    @Autowired
    private  SocketIOServer server;

    @PostConstruct
    public void init(){

        buyerNameSpace = server.addNamespace("/buyer");
        vendorNameSpace = server.addNamespace("/vendor");
        this.setListener(buyerNameSpace);
        this.setListener(vendorNameSpace);
        SocketThreadUtil.socketIOServer=server;
        //启动socketio的线程
        SocketThreadUtil.startSocketThread();

    }


    @Override
    public void pushToBuyer(Collection<?> clientIds, String msg, PushCode pushCode) {
       this.sendPush(buyerNameSpace,(Collection<String>) clientIds,msg,pushCode);

    }

    @Override
    public void pushToBuyer(String clientId, String msg, PushCode pushCode) {
       this.sendPush(buyerNameSpace,clientId,msg,pushCode);
    }

    @Override
    public void pushToVendor(Collection<?> clientIds, String msg, PushCode pushCode) {
         this.sendPush(vendorNameSpace,(Collection<String>) clientIds,msg,pushCode);
    }

    @Override
    public void pushToVendor(String clientId, String msg, PushCode pushCode) {
         this.sendPush(vendorNameSpace,clientId,msg,pushCode);
    }

    @Override
    public void pushToAllBuyer(String msg, PushCode pushCode) {
        pushToAll(buyerNameSpace,msg,pushCode);
    }

    @Override
    public void pushToAllVendor(String msg, PushCode pushCode) {
        pushToAll(vendorNameSpace,msg,pushCode);
    }


    private void setListener(SocketIONamespace socketIONamespace) {
        socketIONamespace.addConnectListener(new ConnectListener() {
            @Override
            public void onConnect(SocketIOClient client) {
                String clientId=client.getHandshakeData().getUrlParams().get("clientId").toString();
                clientId=clientId.replace("[","").replace("]","");
               // clientSessionMap.put(clientId,client.getSessionId());
                keyValueService.put("client_"+clientId,client.getSessionId().toString());
                //检测是否有未发出的信息
                if(keyValueService.exists("expire_"+clientId)){
                    PushData data=keyValueService.getObj("expire_"+clientId,PushData.class);
                    socketIONamespace.getClient(client.getSessionId()).sendEvent("message",data);
                    keyValueService.del("expire_"+clientId);
                }
            }
        });

        socketIONamespace.addDisconnectListener(new DisconnectListener() {
            @Override
            public void onDisconnect(SocketIOClient client) {
                keyValueService.del("?");
            }
        });

    }

    private void sendPush(SocketIONamespace socketIONamespace,String clientId,String message,PushCode pushCode){
        List<String> clientIds=new ArrayList<>();
        clientIds.add(clientId);
        this.sendPush(socketIONamespace,clientIds,message,pushCode);
    }
    private void sendPush(SocketIONamespace socketIONamespace,Collection<String> clientIds,String message,PushCode pushCode){
        int push_code = pushCode != null ? pushCode.getCode() : PushCode.BASE.getCode();
        PushData data=new PushData();
        data.setPushCode(push_code);
        data.setMessage(message);
        for(String clientId:clientIds){
            //socketIONamespace.getBroadcastOperations().sendEvent("message",data);
            try{
                socketIONamespace.getClient(UUID.fromString(keyValueService.get("client_"+clientId))).sendEvent("message",data);
            }catch(NullPointerException e){
                log.error("the client may be sign out,message will be saved 3 days ",e.getMessage());
                keyValueService.putObj("expire_"+clientId,259200,data);
            }

        }

    }

    private void pushToAll(SocketIONamespace namespace,String message,PushCode pushCode){
        int push_code = pushCode != null ? pushCode.getCode() : PushCode.BASE.getCode();
        PushData data=new PushData();
        data.setPushCode(push_code);
        data.setMessage(message);
        namespace.getBroadcastOperations().sendEvent("message",data);
    }

    @Data
    public static class PushData{
        private String message;
        private Integer pushCode;
    }


}
